﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Globalization;
using CalcSharp.Core.General;

namespace CalcSharp.Core.Containers
{
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public class StringData
    {
        public StringData()
        {
            this.desc = "";
            this.value = null;
        }
        public string desc;
        public string value;
    }

    public class StringManager: IMemMan<StringData, string>
    {
        private Dictionary<string, string> Engine;

        public StringManager()
        {
            this.Engine = new Dictionary<string, string>();
        }

        public int Count
        {
            get { return this.Engine.Count; }
        }

        public void Clear()
        {
            this.Engine.Clear();
        }

        public bool isset(string name)
        {
            return Engine.ContainsKey(name.ToLower());
        }

        public void unset(string name)
        {
            string test = Regex.Replace(name, Patterns.String, "-ok-");
            if (test != "-ok-") throw new CSException("Incorrect variable name: " + name);
            Engine.Remove(name.ToLower());
        }

        public int Add(StringData item)
        {
            if (Engine.ContainsKey(item.desc)) Engine[item.desc] = item.value;
            else Engine.Add(item.desc, item.value);
            return Engine.Count;
        }

        /// <summary>
        /// Packs a single variable for serializazion
        /// </summary>
        /// <param name="index">the variable's name</param>
        /// <returns>the packed variable</returns>
        public StringData PackSingle(string name)
        {
            if (string.IsNullOrEmpty(name)) throw new ArgumentException("Name can't be null");
            name = name.ToLower();
            StringData ret = new StringData();
            ret.value = Engine[name];
            ret.desc = name;
            return ret;
        }

        public string[] keys
        {
            get
            {
                string[] rets = new string[this.Engine.Keys.Count];
                this.Engine.Keys.CopyTo(rets, 0);
                return rets;
            }
        }

        public string this[string name]
        {
            get
            {
                name = name.ToLower(CultureInfo.CurrentCulture);
                string test = Regex.Replace(name, Patterns.String, "-ok-");
                if (test != "-ok-") throw new CSException("Incorrect variable name!");
                string val = null;
                if (this.Engine.ContainsKey(name)) val = Engine[name];
                return val;
            }
            set
            {
                name = name.ToLower(CultureInfo.CurrentCulture);
                string test = Regex.Replace(name, Patterns.String, "-ok-");
                if (test != "-ok-") throw new CSException("Incorrect variable name: " + name);
                if (this.Engine.ContainsKey(name)) this.Engine[name] = value;
                else
                {
                    this.Engine.Add(name, value);
                }
            }
        }
    }
}
